﻿#define  _CRT_SECURE_NO_WARNINGS

// map 和 multimap 的使用练习

#include <iostream>
#include <map>

using namespace std;


//////////////////////  map 

// 1. map 也是模版,是容器 
// 2. map 对应 Key \ Value 的场景
// 3. map 底层是红黑树 , 也就是平衡二叉搜索树




// map 中的键值对是存在 pair 这个模版中的 
//                    pair 的 first参数传 Key
//                    pair 的 second参数传 Value

#if 0
int main()
{
	//   K       V   
	map<string, string> m{ {"sort","排序"} };

	return 0;
}
#endif



#if 0
//////////// 构造  --- 与 set 完全类似
int main()
{
	//   K       V   
	map<string, string> dict = { {"left", "左边"}, {"right", "右边"}, 
		                         {"insert", "插入"},{ "string", "字符串" } };

	// 默认构造

	// 迭代器区间构造

	//拷贝构造

	//列表构造


	return 0;
}
#endif 


/////////////////// map  --- 对应 Key/Value 模型 ---- 可以修改 value
//有增删查改功能
//都只与 Key 有关


////// 增  -------------- 只会看 key --- Key 存在了就不插入了
#if 0
int main()
{
	//大小是根据 Key 的字典序比较 , 默认升序
	//   K       V   
	//map<string, string> dict = { {"left", "左边"}, {"right", "右边"}, 
	//							 {"insert", "插入"},{ "string", "字符串" } }; // 升序

	map<string, string, greater<string>> dict = { {"left", "左边"}, {"right", "右边"},
		      					 {"insert", "插入"},{ "string", "字符串" } }; // 降序

	// 键值对存储在 pair 中
	pair<string, string> kv1("cook", "烹饪");

#if 0
	//单个数据插入 ---- 这里返回的是 pair
	//pair<iterator,bool> insert (const value_type& val);


	// 这里有两个 pair 区分
	// insert 返回值 pair 和 键值对 pair

	//pair<T1,T2> ------ 键值对的 pair 是存键值对数据的
	//pair<iterator,bool> ------ 这个 pair 是返回值 , 可以用于查找 
 
	//已经插入的值就不会再次插入
#endif

	dict.insert(kv1);
	
	//auto it = dict.begin();
	//while (it != dict.end())
	//{
	//	// 迭代器(指针)访问解引用
	//	cout << it->first << " : " << it->second << " ";
	//	++it;
	//}

	// make_pair
	dict.insert(pair<string, string>("second", "第二个"));
	//简化
	dict.insert(make_pair("first","第一个"));


	//auto it = dict.begin();
	//while (it != dict.end())
	//{
	//	// 迭代器(指针)访问解引用
	//	cout << it->first << " : " << it->second << " ";
	//	++it;
	//}


	///////////////// C++11 最多使用的

	dict.insert({ "car","汽车" });


	auto it = dict.begin();
	while (it != dict.end())
	{
		// 迭代器(指针)访问解引用
		cout << it->first << " : " << it->second << " ";
		++it;
	}

	return 0;
}
#endif


/////////////////////// 删 --- 找到对应 Key , 删除 Key 和 Value
#if 0
int main()
{
	map<string, string> dict = { {"left", "左边"}, {"right", "右边"}, 
								 {"insert", "插入"},{ "string", "字符串" } }; // 升序

	dict.erase("left");

	auto it = dict.begin();
	while (it != dict.end())
	{
		// 迭代器(指针)访问解引用
		cout << it->first << " : " << it->second << " ";
		++it;
	}

	return 0;
}
#endif

////////// 查 ---- 也是返回找到位置的迭代器

//////////改 --- 改的是 Value

//int main()
//{
//	map<string, string> dict = { {"left", "左边"}, {"right", "右边"},
//								 {"insert", "插入"},{ "string", "字符串" } }; // 升序
//
//	dict.erase("left");
//
//	auto it = dict.begin();
//	while (it != dict.end())
//	{
//		// 改 Value
//		it->second += 'x';
//
//		cout << it->first << " : " << it->second << " ";
//		++it;
//	}
//
//	return 0;
//}


///////////////// operator[] 

//////////////////////////////////// 统计水果次数

#if 0
//方法 一 
int main()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
					"苹果", "香蕉", "苹果", "香蕉" };

	map<string, int> CountMap;
	// 先查找水果在不在map中
	// 1、不在，说明水果第⼀次出现，则插入{水果, 1}
	// 2、在，则查找到的节点中水果对应的次数++

	for (auto& e : arr)
	{
		auto ret = CountMap.find(e);

		//不在
		if (ret == CountMap.end())
		{
			//插入
			CountMap.insert({e,1});
		}
		else
		{
			ret->second++;
		}
	}

	for (const auto& e : CountMap)
	{
		cout << e.first << " : " << e.second << endl;
	}

	return 0;
}
#endif


// 方法二 ---- 用 operator[]  
// 返回值为 vlaue 的引用

// 功能 :  1. 插入  2.查找  3. 修改
#if 0
int main()
{
	map<string, string> dict;
	dict.insert(make_pair("sort", "排序"));

	//插入
	dict["left"];

	//插入 + 修改
	dict["right"] = "右边";

	//查找 --- 必须确定 Key 存在
	cout << dict["right"] << endl; // 查找对应的 value


	auto it = dict.begin();
	while (it != dict.end())
	{
		// 迭代器(指针)访问解引用
		cout << it->first << " : " << it->second << " ";
		++it;
	}
	
	return 0;
}
#endif


//////// 统计水果次数

int main()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
					"苹果", "香蕉", "苹果", "香蕉" };

	map<string, int> countMap;
	for (auto& e : arr)
	{
		countMap[e]++;
		// 不在插入 --- 值+1
		// 在++
	}

	auto it = countMap.begin();
	while (it != countMap.end())
	{
		// 迭代器(指针)访问解引用
		cout << it->first << " : " << it->second <<endl;
		++it;
	}

	return 0;
}






////////////// multimap 允许键值对冗余